<template>
  <div class="demo-container">
    <h2 class="demo-title">Vue 3 高级组合函数演示</h2>
    
    <div class="demo-tabs">
      <div 
        v-for="tab in tabs" 
        :key="tab.id"
        class="tab-button"
        :class="{ active: activeTab === tab.id }"
        @click="activeTab = tab.id"
      >
        {{ tab.name }}
      </div>
    </div>
    
    <div class="tab-content">
      <!-- 基础组合函数 -->
      <div v-show="activeTab === 'basic'" class="tab-pane">
        <div class="demo-section">
          <h3 class="section-title">基础组合函数</h3>
          <div class="demo-description">
            <p><strong>组合函数</strong> 是 Vue 3 中代码复用的重要模式，使用 <code>use</code> 开头的命名约定。</p>
            <p>组合函数让我们能够将组件逻辑提取到可复用的函数中，实现关注点分离和代码复用。</p>
          </div>
          
          <div class="demo-actions">
            <button @click="incrementCounter" class="btn btn-primary">
              增加计数 ({{ counter }})
            </button>
            <button @click="resetCounter" class="btn btn-secondary">
              重置
            </button>
          </div>
          
          <div class="counter-stats">
            <div class="stat-item">
              <span class="stat-label">当前计数:</span>
              <span class="stat-value">{{ counter }}</span>
            </div>
            <div class="stat-item">
              <span class="stat-label">是否为偶数:</span>
              <span class="stat-value" :class="{ even: isEven, odd: !isEven }">
                {{ isEven ? '是' : '否' }}
              </span>
            </div>
            <div class="stat-item">
              <span class="stat-label">是否为正数:</span>
              <span class="stat-value" :class="{ positive: isPositive, negative: !isPositive && counter !== 0 }">
                {{ isPositive ? '是' : (counter < 0 ? '否' : '零') }}
              </span>
            </div>
          </div>
          
          <div class="code-sample">
            <h4>基础计数器组合函数实现</h4>
            <pre>import { ref, computed } from 'vue'

/**
 * 基础计数器组合函数
 * @param {number} initialValue - 初始计数值
 * @returns {Object} 计数器状态和方法
 */
export function useCounter(initialValue = 0) {
  // 响应式状态
  const count = ref(initialValue)
  
  // 计算属性
  const isEven = computed(() => count.value % 2 === 0)
  const isPositive = computed(() => count.value > 0)
  
  // 方法
  function increment() {
    count.value++
  }
  
  function decrement() {
    count.value--
  }
  
  function reset() {
    count.value = initialValue
  }
  
  function setValue(newValue) {
    count.value = newValue
  }
  
  // 返回公共接口
  return {
    count,
    isEven,
    isPositive,
    increment,
    decrement,
    reset,
    setValue
  }
}

// 在组件中使用
const { count, isEven, isPositive, increment, reset } = useCounter(0)</pre>
          </div>
        </div>
      </div>
      
      <!-- 异步数据获取 -->
      <div v-show="activeTab === 'async'" class="tab-pane">
        <div class="demo-section">
          <h3 class="section-title">异步数据获取组合函数</h3>
          <div class="demo-description">
            <p><strong>useFetch</strong> 组合函数封装了异步数据获取的逻辑，包括加载状态、错误处理和数据缓存。</p>
            <p>这种模式让组件代码更加清晰，同时提供了一致的错误处理和加载状态管理。</p>
          </div>
          
          <div class="demo-actions">
            <button 
              @click="fetchUserData(1)" 
              class="btn btn-primary"
              :disabled="loading"
            >
              {{ loading ? '加载中...' : '获取用户数据' }}
            </button>
            <button 
              @click="fetchPosts(1)" 
              class="btn btn-secondary"
              :disabled="loading"
            >
              获取文章列表
            </button>
            <button @click="clearData" class="btn btn-outline">
              清除数据
            </button>
          </div>
          
          <div v-if="error" class="error-message">
            <strong>错误:</strong> {{ error.message }}
          </div>
          
          <div v-if="loading" class="loading-indicator">
            <div class="spinner"></div>
            <p>正在加载数据...</p>
          </div>
          
          <div v-if="data && !loading" class="data-display">
            <h4>获取的数据:</h4>
            <div class="data-content">
              <pre>{{ JSON.stringify(data, null, 2) }}</pre>
            </div>
          </div>
          
          <div class="fetch-stats">
            <div class="stat-item">
              <span class="stat-label">请求次数:</span>
              <span class="stat-value">{{ requestCount }}</span>
            </div>
            <div class="stat-item">
              <span class="stat-label">缓存命中:</span>
              <span class="stat-value">{{ cacheHits }}</span>
            </div>
          </div>
          
          <div class="code-sample">
            <h4>异步数据获取组合函数</h4>
            <pre>import { ref, isRef, unref } from 'vue'

/**
 * 通用异步数据获取组合函数
 * @param {Function|string} fetchFn - 获取数据的函数或URL
 * @param {Object} options - 配置选项
 * @returns {Object} 数据、加载状态、错误和刷新方法
 */
export function useFetch(fetchFn, options = {}) {
  const {
    immediate = true,
    cache = true,
    transform = data => data
  } = options
  
  // 响应式状态
  const data = ref(null)
  const loading = ref(false)
  const error = ref(null)
  const requestCount = ref(0)
  
  // 缓存
  const cacheMap = new Map()
  const cacheHits = ref(0)
  
  // 执行请求
  async function executeFetch(...args) {
    const key = typeof fetchFn === 'string' 
      ? `${fetchFn}_${JSON.stringify(args)}` 
      : `${fetchFn.name}_${JSON.stringify(args)}`
    
    // 检查缓存
    if (cache && cacheMap.has(key)) {
      data.value = cacheMap.get(key)
      cacheHits.value++
      return
    }
    
    loading.value = true
    error.value = null
    requestCount.value++
    
    try {
      let result
      if (typeof fetchFn === 'string') {
        // 处理URL字符串
        const response = await fetch(fetchFn)
        if (!response.ok) {
          throw new Error(`HTTP error! status: ${response.status}`)
        }
        result = await response.json()
      } else {
        // 处理函数
        result = await fetchFn(...args)
      }
      
      // 转换数据
      const transformedData = transform(result)
      data.value = transformedData
      
      // 更新缓存
      if (cache) {
        cacheMap.set(key, transformedData)
      }
    } catch (err) {
      error.value = err
    } finally {
      loading.value = false
    }
  }
  
  // 刷新数据
  function refresh(...args) {
    // 清除缓存条目
    const key = typeof fetchFn === 'string' 
      ? `${fetchFn}_${JSON.stringify(args)}` 
      : `${fetchFn.name}_${JSON.stringify(args)}`
    
    if (cacheMap.has(key)) {
      cacheMap.delete(key)
    }
    
    return executeFetch(...args)
  }
  
  // 清除缓存
  function clearCache() {
    cacheMap.clear()
  }
  
  // 立即执行（如果需要）
  if (immediate) {
    executeFetch()
  }
  
  // 返回公共接口
  return {
    data,
    loading,
    error,
    requestCount,
    cacheHits,
    executeFetch,
    refresh,
    clearCache
  }
}

// 模拟API请求
async function fetchUser(id) {
  // 模拟网络延迟
  await new Promise(resolve => setTimeout(resolve, 800))
  return {
    id,
    name: `User ${id}`,
    email: `user${id}@example.com`,
    createdAt: new Date().toISOString()
  }
}

// 在组件中使用
const { data, loading, error, executeFetch } = useFetch(fetchUser, {
  immediate: false,
  cache: true
})</pre>
          </div>
        </div>
      </div>
      
      <!-- 状态管理 -->
      <div v-show="activeTab === 'state'" class="tab-pane">
        <div class="demo-section">
          <h3 class="section-title">响应式状态管理组合函数</h3>
          <div class="demo-description">
            <p><strong>useLocalStorage</strong> 和 <strong>useSessionStorage</strong> 组合函数提供了与浏览器存储交互的响应式状态管理。</p>
            <p>这些组合函数使得在组件中使用存储变得简单，同时保持数据的响应性。</p>
          </div>
          
          <div class="storage-controls">
            <div class="storage-group">
              <h4>LocalStorage</h4>
              <div class="input-group">
                <label for="localStorageKey">键:</label>
                <input id="localStorageKey" v-model="localStorageKey" class="form-input" placeholder="输入键名">
              </div>
              <div class="input-group">
                <label for="localStorageValue">值:</label>
                <input id="localStorageValue" v-model="localStorageValue" class="form-input" placeholder="输入值">
              </div>
              <div class="action-buttons">
                <button @click="saveToLocalStorage" class="btn btn-primary">
                  保存
                </button>
                <button @click="loadFromLocalStorage" class="btn btn-secondary">
                  加载
                </button>
                <button @click="removeFromLocalStorage" class="btn btn-danger">
                  删除
                </button>
              </div>
            </div>
            
            <div class="storage-group">
              <h4>SessionStorage</h4>
              <div class="input-group">
                <label for="sessionStorageKey">键:</label>
                <input id="sessionStorageKey" v-model="sessionStorageKey" class="form-input" placeholder="输入键名">
              </div>
              <div class="input-group">
                <label for="sessionStorageValue">值:</label>
                <input id="sessionStorageValue" v-model="sessionStorageValue" class="form-input" placeholder="输入值">
              </div>
              <div class="action-buttons">
                <button @click="saveToSessionStorage" class="btn btn-primary">
                  保存
                </button>
                <button @click="loadFromSessionStorage" class="btn btn-secondary">
                  加载
                </button>
                <button @click="removeFromSessionStorage" class="btn btn-danger">
                  删除
                </button>
              </div>
            </div>
          </div>
          
          <div class="storage-preview">
            <div class="preview-group">
              <h4>LocalStorage 内容:</h4>
              <div class="preview-content">
                <pre v-if="localStorageData">{{ JSON.stringify(localStorageData, null, 2) }}</pre>
                <p v-else class="empty-message">LocalStorage 为空</p>
              </div>
            </div>
            
            <div class="preview-group">
              <h4>SessionStorage 内容:</h4>
              <div class="preview-content">
                <pre v-if="sessionStorageData">{{ JSON.stringify(sessionStorageData, null, 2) }}</pre>
                <p v-else class="empty-message">SessionStorage 为空</p>
              </div>
            </div>
          </div>
          
          <div class="code-sample">
            <h4>存储组合函数实现</h4>
            <pre>import { ref, watch, onMounted } from 'vue'

/**
 * 本地存储组合函数
 * @param {string} key - 存储键名
 * @param {*} defaultValue - 默认值
 * @returns {Object} 响应式值和方法
 */
export function useLocalStorage(key, defaultValue = null) {
  return useStorage('localStorage', key, defaultValue)
}

/**
 * 会话存储组合函数
 * @param {string} key - 存储键名
 * @param {*} defaultValue - 默认值
 * @returns {Object} 响应式值和方法
 */
export function useSessionStorage(key, defaultValue = null) {
  return useStorage('sessionStorage', key, defaultValue)
}

/**
 * 通用存储组合函数
 * @param {string} storageType - 存储类型 ('localStorage' 或 'sessionStorage')
 * @param {string} key - 存储键名
 * @param {*} defaultValue - 默认值
 * @returns {Object} 响应式值和方法
 */
function useStorage(storageType, key, defaultValue = null) {
  // 获取存储对象
  const storage = window[storageType]
  
  // 从存储加载初始值
  function getInitialValue() {
    try {
      const stored = storage.getItem(key)
      return stored !== null ? JSON.parse(stored) : defaultValue
    } catch (error) {
      console.error(`Error loading from ${storageType}:`, error)
      return defaultValue
    }
  }
  
  // 响应式值
  const value = ref(getInitialValue())
  
  // 保存到存储
  function save() {
    try {
      storage.setItem(key, JSON.stringify(value.value))
    } catch (error) {
      console.error(`Error saving to ${storageType}:`, error)
    }
  }
  
  // 从存储加载
  function load() {
    value.value = getInitialValue()
  }
  
  // 从存储删除
  function remove() {
    try {
      storage.removeItem(key)
      value.value = defaultValue
    } catch (error) {
      console.error(`Error removing from ${storageType}:`, error)
    }
  }
  
  // 清除所有存储
  function clearAll() {
    try {
      storage.clear()
      value.value = defaultValue
    } catch (error) {
      console.error(`Error clearing ${storageType}:`, error)
    }
  }
  
  // 监听值变化并保存到存储
  watch(value, () => {
    save()
  }, { deep: true })
  
  // 组件挂载时加载
  onMounted(() => {
    load()
  })
  
  // 返回公共接口
  return {
    value,
    save,
    load,
    remove,
    clearAll
  }
}

// 在组件中使用
const { value: userSettings } = useLocalStorage('user-settings', {
  theme: 'light',
  notifications: true,
  language: 'zh-CN'
})</pre>
          </div>
        </div>
      </div>
      
      <!-- 浏览器API集成 -->
      <div v-show="activeTab === 'browser'" class="tab-pane">
        <div class="demo-section">
          <h3 class="section-title">浏览器API集成组合函数</h3>
          <div class="demo-description">
            <p><strong>浏览器API组合函数</strong> 封装了各种浏览器API，使得在Vue组件中使用这些API变得简单和响应式。</p>
            <p>这些组合函数提供了统一的接口，同时处理了浏览器兼容性和生命周期管理。</p>
          </div>
          
          <div class="browser-apis">
            <div class="api-card">
              <h4>鼠标位置跟踪</h4>
              <div class="api-content">
                <div class="mouse-position">
                  <div class="position-item">
                    <span class="position-label">X 坐标:</span>
                    <span class="position-value">{{ mousePosition.x }}</span>
                  </div>
                  <div class="position-item">
                    <span class="position-label">Y 坐标:</span>
                    <span class="position-value">{{ mousePosition.y }}</span>
                  </div>
                </div>
                <div class="action-buttons">
                  <button @click="toggleMouseTracking" class="btn btn-primary">
                    {{ isTrackingMouse ? '停止跟踪' : '开始跟踪' }}
                  </button>
                </div>
              </div>
            </div>
            
            <div class="api-card">
              <h4>窗口大小监听</h4>
              <div class="api-content">
                <div class="window-size">
                  <div class="size-item">
                    <span class="size-label">宽度:</span>
                    <span class="size-value">{{ windowSize.width }}px</span>
                  </div>
                  <div class="size-item">
                    <span class="size-label">高度:</span>
                    <span class="size-value">{{ windowSize.height }}px</span>
                  </div>
                  <div class="size-item">
                    <span class="size-label">设备像素比:</span>
                    <span class="size-value">{{ windowSize.devicePixelRatio }}</span>
                  </div>
                </div>
                <div class="window-type">
                  <span class="type-label">屏幕类型:</span>
                  <span class="type-value" :class="windowType">
                    {{ getWindowTypeName() }}
                  </span>
                </div>
              </div>
            </div>
            
            <div class="api-card">
              <h4>网络状态监控</h4>
              <div class="api-content">
                <div class="network-status">
                  <div class="status-item">
                    <span class="status-label">在线状态:</span>
                    <span class="status-value" :class="{ online: isOnline, offline: !isOnline }">
                      {{ isOnline ? '在线' : '离线' }}
                    </span>
                  </div>
                  <div class="status-item" v-if="networkInfo">
                    <span class="status-label">连接类型:</span>
                    <span class="status-value">{{ networkInfo.effectiveType }}</span>
                  </div>
                  <div class="status-item" v-if="networkInfo">
                    <span class="status-label">下行速度:</span>
                    <span class="status-value">{{ (networkInfo.downlink || 0).toFixed(1) }} Mbps</span>
                  </div>
                </div>
              </div>
            </div>
            
            <div class="api-card">
              <h4>剪贴板操作</h4>
              <div class="api-content">
                <div class="input-group">
                  <label for="clipboardText">文本:</label>
                  <input id="clipboardText" v-model="clipboardText" class="form-input" placeholder="输入要复制的文本">
                </div>
                <div class="action-buttons">
                  <button @click="copyToClipboard" class="btn btn-primary">
                    复制到剪贴板
                  </button>
                  <button @click="pasteFromClipboard" class="btn btn-secondary">
                    从剪贴板粘贴
                  </button>
                </div>
                <div v-if="clipboardMessage" class="clipboard-message" :class="clipboardMessageType">
                  {{ clipboardMessage }}
                </div>
              </div>
            </div>
          </div>
          
          <div class="code-sample">
            <h4>浏览器API组合函数示例</h4>
            <pre>import { ref, onMounted, onUnmounted, watch } from 'vue'

/**
 * 鼠标位置跟踪组合函数
 * @returns {Object} 鼠标位置和控制方法
 */
export function useMouse() {
  const x = ref(0)
  const y = ref(0)
  const isTracking = ref(false)
  
  function updateMousePosition(event) {
    x.value = event.clientX
    y.value = event.clientY
  }
  
  function startTracking() {
    if (!isTracking.value) {
      window.addEventListener('mousemove', updateMousePosition)
      isTracking.value = true
    }
  }
  
  function stopTracking() {
    if (isTracking.value) {
      window.removeEventListener('mousemove', updateMousePosition)
      isTracking.value = false
    }
  }
  
  function toggleTracking() {
    isTracking.value ? stopTracking() : startTracking()
  }
  
  // 组件卸载时清理
  onUnmounted(() => {
    stopTracking()
  })
  
  return {
    x,
    y,
    isTracking,
    startTracking,
    stopTracking,
    toggleTracking
  }
}

/**
 * 窗口大小监听组合函数
 * @returns {Object} 窗口大小信息
 */
export function useWindowSize() {
  const width = ref(window.innerWidth)
  const height = ref(window.innerHeight)
  const devicePixelRatio = ref(window.devicePixelRatio)
  
  function updateSize() {
    width.value = window.innerWidth
    height.value = window.innerHeight
    devicePixelRatio.value = window.devicePixelRatio
  }
  
  onMounted(() => {
    window.addEventListener('resize', updateSize)
    window.addEventListener('devicePixelRatioChange', updateSize)
  })
  
  onUnmounted(() => {
    window.removeEventListener('resize', updateSize)
    window.removeEventListener('devicePixelRatioChange', updateSize)
  })
  
  return {
    width,
    height,
    devicePixelRatio
  }
}

/**
 * 网络状态监控组合函数
 * @returns {Object} 网络状态信息
 */
export function useNetwork() {
  const isOnline = ref(navigator.onLine)
  const networkInfo = ref(null)
  
  function updateNetworkInfo() {
    if (navigator.connection) {
      networkInfo.value = {
        type: navigator.connection.type,
        effectiveType: navigator.connection.effectiveType,
        downlink: navigator.connection.downlink,
        rtt: navigator.connection.rtt,
        saveData: navigator.connection.saveData
      }
    }
  }
  
  function handleOnline() {
    isOnline.value = true
    updateNetworkInfo()
  }
  
  function handleOffline() {
    isOnline.value = false
  }
  
  onMounted(() => {
    window.addEventListener('online', handleOnline)
    window.addEventListener('offline', handleOffline)
    
    if (navigator.connection) {
      navigator.connection.addEventListener('change', updateNetworkInfo)
      updateNetworkInfo()
    }
  })
  
  onUnmounted(() => {
    window.removeEventListener('online', handleOnline)
    window.removeEventListener('offline', handleOffline)
    
    if (navigator.connection) {
      navigator.connection.removeEventListener('change', updateNetworkInfo)
    }
  })
  
  return {
    isOnline,
    networkInfo
  }
}

/**
 * 剪贴板操作组合函数
 * @returns {Object} 剪贴板操作方法
 */
export function useClipboard() {
  const text = ref('')
  const error = ref(null)
  
  async function copyToClipboard(content) {
    try {
      error.value = null
      await navigator.clipboard.writeText(content)
      text.value = content
      return true
    } catch (err) {
      error.value = err
      console.error('Failed to copy text:', err)
      return false
    }
  }
  
  async function pasteFromClipboard() {
    try {
      error.value = null
      const pastedText = await navigator.clipboard.readText()
      text.value = pastedText
      return pastedText
    } catch (err) {
      error.value = err
      console.error('Failed to paste text:', err)
      return null
    }
  }
  
  return {
    text,
    error,
    copyToClipboard,
    pasteFromClipboard
  }
}

// 在组件中使用示例
const { x, y, startTracking } = useMouse()
const { width, height } = useWindowSize()
const { isOnline } = useNetwork()
const { copyToClipboard } = useClipboard()</pre>
          </div>
        </div>
      </div>
      
      <!-- 高级组合函数 -->
      <div v-show="activeTab === 'advanced'" class="tab-pane">
        <div class="demo-section">
          <h3 class="section-title">高级组合函数模式</h3>
          <div class="demo-description">
            <p><strong>高级组合函数模式</strong> 展示了如何创建更复杂、更强大的组合函数，包括组合函数嵌套、生命周期管理和性能优化。</p>
            <p>这些模式可以帮助你构建更加模块化、可维护的Vue应用。</p>
          </div>
          
          <div class="advanced-patterns">
            <div class="pattern-card">
              <h4 class="pattern-title">1. 组合函数嵌套</h4>
              <div class="pattern-content">
                <p>组合函数可以相互嵌套使用，形成功能强大的组合逻辑：</p>
                <div class="code-snippet">
                  <pre>// 嵌套组合函数示例
import { ref, computed } from 'vue'
import { useCounter } from './useCounter'
import { useLocalStorage } from './useLocalStorage'

/**
 * 高级计数器组合函数 - 集成本地存储
 */
export function usePersistentCounter(key = 'counter', initialValue = 0) {
  // 使用基本计数器
  const { count, increment, decrement, reset } = useCounter(initialValue)
  
  // 使用本地存储
  const { value: storedValue, save: saveToStorage } = useLocalStorage(key, initialValue)
  
  // 当存储值变化时更新计数器
  computed(() => {
    if (count.value !== storedValue.value) {
      count.value = storedValue.value
    }
  })
  
  // 当计数器变化时保存到存储
  computed(() => {
    if (count.value !== storedValue.value) {
      storedValue.value = count.value
      saveToStorage()
    }
  })
  
  // 增强的重置方法
  function resetCounter() {
    reset()
    storedValue.value = initialValue
    saveToStorage()
  }
  
  // 返回增强的接口
  return {
    ...useCounter(count.value),
    reset: resetCounter
  }
}

// 使用示例
const { count, increment, reset } = usePersistentCounter('app-counter', 10)</pre>
                </div>
              </div>
            </div>
            
            <div class="pattern-card">
              <h4 class="pattern-title">2. 条件组合函数</h4>
              <div class="pattern-content">
                <p>根据条件动态选择使用不同的组合函数：</p>
                <div class="code-snippet">
                  <pre>// 条件组合函数示例
import { ref, watch } from 'vue'

/**
 * 条件缓存组合函数
 */
export function useConditionalCache(getDataFn, options = {}) {
  const {
    useLocalCache = true,
    useMemoryCache = true,
    ttl = 5 * 60 * 1000 // 默认5分钟
  } = options
  
  const data = ref(null)
  const loading = ref(false)
  const error = ref(null)
  
  // 内存缓存
  const memoryCache = new Map()
  
  // 检查缓存是否有效
  function isCacheValid(timestamp) {
    return Date.now() - timestamp \u003c ttl
  }
  
  // 获取数据
  async function fetchData(...args) {
    const cacheKey = JSON.stringify(args)
    
    // 检查内存缓存
    if (useMemoryCache \u0026\u0026 memoryCache.has(cacheKey)) {
      const cached = memoryCache.get(cacheKey)
      if (isCacheValid(cached.timestamp)) {
        data.value = cached.data
        return
      }
    }
    
    // 检查本地存储缓存
    let localStorageCache = null
    if (useLocalCache \u0026\u0026 typeof localStorage !== 'undefined') {
      try {
        const stored = localStorage.getItem(`cache_${cacheKey}`)
        if (stored) {
          localStorageCache = JSON.parse(stored)
          if (isCacheValid(localStorageCache.timestamp)) {
            data.value = localStorageCache.data
            if (useMemoryCache) {
              memoryCache.set(cacheKey, localStorageCache)
            }
            return
          }
        }
      } catch (err) {
        console.error('Error reading from localStorage:', err)
      }
    }
    
    // 获取新数据
    loading.value = true
    error.value = null
    
    try {
      const result = await getDataFn(...args)
      data.value = result
      
      // 更新缓存
      const cacheData = { data: result, timestamp: Date.now() }
      
      if (useMemoryCache) {
        memoryCache.set(cacheKey, cacheData)
      }
      
      if (useLocalCache \u0026\u0026 typeof localStorage !== 'undefined') {
        try {
          localStorage.setItem(`cache_${cacheKey}`, JSON.stringify(cacheData))
        } catch (err) {
          console.error('Error writing to localStorage:', err)
        }
      }
    } catch (err) {
      error.value = err
    } finally {
      loading.value = false
    }
  }
  
  // 清除缓存
  function clearCache() {
    memoryCache.clear()
    
    if (useLocalCache \u0026\u0026 typeof localStorage !== 'undefined') {
      try {
        // 清除所有以cache_开头的键
        Object.keys(localStorage).forEach(key => {
          if (key.startsWith('cache_')) {
            localStorage.removeItem(key)
          }
        })
      } catch (err) {
        console.error('Error clearing localStorage:', err)
      }
    }
  }
  
  // 条件配置变更时重新获取数据
  watch(() => [useLocalCache, useMemoryCache], () => {
    // 配置变更时可以选择刷新数据
  })
  
  return {
    data,
    loading,
    error,
    fetchData,
    clearCache
  }
}

// 使用示例
const { data, fetchData } = useConditionalCache(fetchUserData, {
  useLocalCache: true,
  useMemoryCache: true,
  ttl: 10 * 60 * 1000 // 10分钟
})</pre>
                </div>
              </div>
            </div>
            
            <div class="pattern-card">
              <h4 class="pattern-title">3. 生命周期管理组合函数</h4>
              <div class="pattern-content">
                <p>管理异步操作和资源的生命周期：</p>
                <div class="code-snippet">
                  <pre>// 生命周期管理组合函数
import { ref, onUnmounted } from 'vue'

/**
 * 定时器组合函数
 */
export function useTimer(callback, interval = 1000, immediate = false) {
  const isActive = ref(false)
  let timerId = null
  
  // 启动定时器
  function start() {
    if (isActive.value) return
    
    // 立即执行回调（如果需要）
    if (immediate) {
      callback()
    }
    
    timerId = setInterval(callback, interval)
    isActive.value = true
  }
  
  // 停止定时器
  function stop() {
    if (!isActive.value) return
    
    clearInterval(timerId)
    timerId = null
    isActive.value = false
  }
  
  // 暂停定时器
  function pause() {
    stop()
  }
  
  // 恢复定时器
  function resume() {
    start()
  }
  
  // 切换状态
  function toggle() {
    isActive.value ? stop() : start()
  }
  
  // 更新间隔
  function updateInterval(newInterval) {
    const wasActive = isActive.value
    if (wasActive) {
      stop()
    }
    interval = newInterval
    if (wasActive) {
      start()
    }
  }
  
  // 组件卸载时清理
  onUnmounted(() => {
    stop()
  })
  
  return {
    isActive,
    start,
    stop,
    pause,
    resume,
    toggle,
    updateInterval
  }
}

/**
 * 动画帧组合函数
 */
export function useAnimationFrame(callback, autoStart = false) {
  const isActive = ref(autoStart)
  let animationId = null
  
  function animate(timestamp) {
    if (!isActive.value) return
    
    callback(timestamp)
    animationId = requestAnimationFrame(animate)
  }
  
  function start() {
    if (isActive.value) return
    
    isActive.value = true
    animationId = requestAnimationFrame(animate)
  }
  
  function stop() {
    if (!isActive.value) return
    
    isActive.value = false
    if (animationId) {
      cancelAnimationFrame(animationId)
      animationId = null
    }
  }
  
  function toggle() {
    isActive.value ? stop() : start()
  }
  
  // 组件卸载时清理
  onUnmounted(() => {
    stop()
  })
  
  // 自动启动
  if (autoStart) {
    start()
  }
  
  return {
    isActive,
    start,
    stop,
    toggle
  }
}

// 使用示例
const { start, stop, isActive } = useTimer(() => {
  console.log('Timer tick')
}, 5000)

const { toggle } = useAnimationFrame((timestamp) => {
  // 执行动画逻辑
  updateAnimation(timestamp)
})</pre>
                </div>
              </div>
            </div>
            
            <div class="pattern-card">
              <h4 class="pattern-title">4. 组合函数工厂模式</h4>
              <div class="pattern-content">
                <p>使用工厂模式创建配置化的组合函数：</p>
                <div class="code-snippet">
                  <pre>// 组合函数工厂模式
import { ref, computed } from 'vue'

/**
 * 创建验证器组合函数的工厂
 */
export function createValidator(options = {}) {
  const { 
    validations = {},
    defaultMessage = '输入无效'
  } = options
  
  /**
   * 表单验证组合函数
   */
  return function useValidator(formData) {
    const errors = ref({})
    const isValid = computed(() => Object.keys(errors.value).length === 0)
    
    // 验证单个字段
    function validateField(fieldName, value) {
      const fieldValidations = validations[fieldName]
      if (!fieldValidations) return true
      
      // 清除该字段的错误
      if (errors.value[fieldName]) {
        delete errors.value[fieldName]
      }
      
      // 执行验证规则
      for (const [ruleName, ruleConfig] of Object.entries(fieldValidations)) {
        const [rule, message = defaultMessage] = Array.isArray(ruleConfig) 
          ? ruleConfig 
          : [ruleConfig, defaultMessage]
        
        let isValid = true
        
        // 执行验证
        if (typeof rule === 'function') {
          isValid = rule(value, formData.value)
        } else if (rule instanceof RegExp) {
          isValid = rule.test(value)
        } else if (typeof rule === 'object') {
          // 内置规则
          if (rule.required && !value) {
            isValid = false
          } else if (rule.min && value.length \u003c rule.min) {
            isValid = false
          } else if (rule.max && value.length \u003e rule.max) {
            isValid = false
          }
        }
        
        if (!isValid) {
          errors.value[fieldName] = message
          return false
        }
      }
      
      return true
    }
    
    // 验证整个表单
    function validateForm() {
      errors.value = {}
      let isValid = true
      
      for (const fieldName in formData.value) {
        if (!validateField(fieldName, formData.value[fieldName])) {
          isValid = false
        }
      }
      
      return isValid
    }
    
    // 清除所有错误
    function clearErrors() {
      errors.value = {}
    }
    
    // 清除特定字段的错误
    function clearFieldError(fieldName) {
      if (errors.value[fieldName]) {
        delete errors.value[fieldName]
      }
    }
    
    return {
      errors,
      isValid,
      validateField,
      validateForm,
      clearErrors,
      clearFieldError
    }
  }
}

// 使用示例
// 创建自定义验证器
const useFormValidator = createValidator({
  defaultMessage: '此字段无效',
  validations: {
    email: [
      { required: true },
      /^[^\s@]+@[^\s@]+\.[^\s@]+$/,
      (value) => value.length \u003c 255 || '邮箱长度不能超过255个字符'
    ],
    password: [
      { required: true },
      { min: 8 },
      /[A-Z]/.test,
      /[0-9]/.test,
      /[^A-Za-z0-9]/.test
    ]
  }
})

// 在组件中使用
const formData = ref({
  email: '',
  password: ''
})

const { errors, isValid, validateForm } = useFormValidator(formData)</pre>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, reactive, computed, onMounted, onUnmounted, watch } from 'vue';

// 选项卡状态
const activeTab = ref('basic');
const tabs = [
  { id: 'basic', name: '基础组合函数' },
  { id: 'async', name: '异步数据获取' },
  { id: 'state', name: '状态管理' },
  { id: 'browser', name: '浏览器API集成' },
  { id: 'advanced', name: '高级组合函数模式' }
];

// 基础计数器演示
const counter = ref(0);
const isEven = computed(() => counter.value % 2 === 0);
const isPositive = computed(() => counter.value > 0);

const incrementCounter = () => {
  counter.value++;
};

const resetCounter = () => {
  counter.value = 0;
};

// 异步数据获取演示
const data = ref(null);
const loading = ref(false);
const error = ref(null);
const requestCount = ref(0);
const cacheHits = ref(0);

// 模拟API请求
const mockFetchUser = (id) => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      if (Math.random() > 0.1) { // 90%成功率
        resolve({
          id,
          name: `User ${id}`,
          email: `user${id}@example.com`,
          createdAt: new Date().toISOString(),
          role: 'user',
          profile: {
            avatar: `https://randomuser.me/api/portraits/men/${id}.jpg`,
            bio: `This is user ${id}'s bio`,
            location: 'Some City, Country'
          },
          stats: {
            posts: Math.floor(Math.random() * 100),
            followers: Math.floor(Math.random() * 1000),
            following: Math.floor(Math.random() * 500)
          }
        });
      } else {
        reject(new Error('Network error occurred'));
      }
    }, 800);
  });
};

const mockFetchPosts = (userId) => {
  return new Promise((resolve) => {
    setTimeout(() => {
      const posts = Array.from({ length: 5 }, (_, index) => ({
        id: index + 1,
        userId,
        title: `Post ${index + 1} by User ${userId}`,
        content: `This is the content of post ${index + 1}`,
        createdAt: new Date(Date.now() - index * 86400000).toISOString(),
        likes: Math.floor(Math.random() * 100),
        comments: Math.floor(Math.random() * 20)
      }));
      resolve(posts);
    }, 600);
  });
};

// 数据缓存
const dataCache = new Map();

const fetchUserData = async (id) => {
  const cacheKey = `user_${id}`;
  
  // 检查缓存
  if (dataCache.has(cacheKey)) {
    data.value = dataCache.get(cacheKey);
    cacheHits.value++;
    return;
  }
  
  loading.value = true;
  error.value = null;
  requestCount.value++;
  
  try {
    const result = await mockFetchUser(id);
    data.value = result;
    dataCache.set(cacheKey, result);
  } catch (err) {
    error.value = err;
  } finally {
    loading.value = false;
  }
};

const fetchPosts = async (userId) => {
  const cacheKey = `posts_${userId}`;
  
  // 检查缓存
  if (dataCache.has(cacheKey)) {
    data.value = dataCache.get(cacheKey);
    cacheHits.value++;
    return;
  }
  
  loading.value = true;
  error.value = null;
  requestCount.value++;
  
  try {
    const result = await mockFetchPosts(userId);
    data.value = result;
    dataCache.set(cacheKey, result);
  } catch (err) {
    error.value = err;
  } finally {
    loading.value = false;
  }
};

const clearData = () => {
  data.value = null;
  error.value = null;
};

// 存储管理演示
const localStorageKey = ref('demo-key');
const localStorageValue = ref('demo-value');
const sessionStorageKey = ref('demo-session-key');
const sessionStorageValue = ref('demo-session-value');

const localStorageData = ref(null);
const sessionStorageData = ref(null);

const saveToLocalStorage = () => {
  try {
    localStorage.setItem(localStorageKey.value, localStorageValue.value);
    loadAllLocalStorage();
  } catch (e) {
    console.error('Error saving to localStorage:', e);
  }
};

const loadFromLocalStorage = () => {
  try {
    localStorageValue.value = localStorage.getItem(localStorageKey.value) || '';
  } catch (e) {
    console.error('Error loading from localStorage:', e);
  }
};

const removeFromLocalStorage = () => {
  try {
    localStorage.removeItem(localStorageKey.value);
    if (localStorageKey.value === localStorageValue.value) {
      localStorageValue.value = '';
    }
    loadAllLocalStorage();
  } catch (e) {
    console.error('Error removing from localStorage:', e);
  }
};

const saveToSessionStorage = () => {
  try {
    sessionStorage.setItem(sessionStorageKey.value, sessionStorageValue.value);
    loadAllSessionStorage();
  } catch (e) {
    console.error('Error saving to sessionStorage:', e);
  }
};

const loadFromSessionStorage = () => {
  try {
    sessionStorageValue.value = sessionStorage.getItem(sessionStorageKey.value) || '';
  } catch (e) {
    console.error('Error loading from sessionStorage:', e);
  }
};

const removeFromSessionStorage = () => {
  try {
    sessionStorage.removeItem(sessionStorageKey.value);
    if (sessionStorageKey.value === sessionStorageValue.value) {
      sessionStorageValue.value = '';
    }
    loadAllSessionStorage();
  } catch (e) {
    console.error('Error removing from sessionStorage:', e);
  }
};

const loadAllLocalStorage = () => {
  try {
    const data = {};
    for (let i = 0; i <localStorage.length; i++) {
      const key = localStorage.key(i);
      data[key] = localStorage.getItem(key);
    }
    localStorageData.value = data;
  } catch (e) {
    console.error('Error loading all localStorage:', e);
  }
};

const loadAllSessionStorage = () => {
  try {
    const data = {};
    for (let i = 0; i < sessionStorage.length; i++) {
      const key = sessionStorage.key(i);
      data[key] = sessionStorage.getItem(key);
    }
    sessionStorageData.value = data;
  } catch (e) {
    console.error('Error loading all sessionStorage:', e);
  }
};

// 浏览器API演示
// 鼠标位置
const mousePosition = reactive({ x: 0, y: 0 });
const isTrackingMouse = ref(false);

const updateMousePosition = (event) => {
  mousePosition.x = event.clientX;
  mousePosition.y = event.clientY;
};

const toggleMouseTracking = () => {
  isTrackingMouse.value = !isTrackingMouse.value;
  
  if (isTrackingMouse.value) {
    window.addEventListener('mousemove', updateMousePosition);
  } else {
    window.removeEventListener('mousemove', updateMousePosition);
  }
};

// 窗口大小
const windowSize = reactive({
  width: window.innerWidth,
  height: window.innerHeight,
  devicePixelRatio: window.devicePixelRatio
});

const updateWindowSize = () => {
  windowSize.width = window.innerWidth;
  windowSize.height = window.innerHeight;
  windowSize.devicePixelRatio = window.devicePixelRatio;
};

const windowType = computed(() => {
  if (windowSize.width < 640) return 'mobile';
  if (windowSize.width < 1024) return 'tablet';
  return 'desktop';
});

const getWindowTypeName = () => {
  switch (windowType.value) {
    case 'mobile': return '移动设备';
    case 'tablet': return '平板设备';
    case 'desktop': return '桌面设备';
    default: return '未知设备';
  }
};

// 网络状态
const isOnline = ref(navigator.onLine);
const networkInfo = ref(null);

const updateNetworkInfo = () => {
  if (navigator.connection) {
    networkInfo.value = {
      type: navigator.connection.type,
      effectiveType: navigator.connection.effectiveType,
      downlink: navigator.connection.downlink,
      rtt: navigator.connection.rtt,
      saveData: navigator.connection.saveData
    };
  }
};

const handleOnline = () => {
  isOnline.value = true;
};

const handleOffline = () => {
  isOnline.value = false;
};

// 剪贴板
const clipboardText = ref('');
const clipboardMessage = ref('');
const clipboardMessageType = ref('');

const copyToClipboard = async () => {
  try {
    await navigator.clipboard.writeText(clipboardText.value);
    clipboardMessage.value = '文本已复制到剪贴板';
    clipboardMessageType.value = 'success';
  } catch (err) {
    clipboardMessage.value = '复制失败: ' + err.message;
    clipboardMessageType.value = 'error';
    console.error('Failed to copy:', err);
  }
  
  setTimeout(() => {
    clipboardMessage.value = '';
    clipboardMessageType.value = '';
  }, 3000);
};

const pasteFromClipboard = async () => {
  try {
    const text = await navigator.clipboard.readText();
    clipboardText.value = text;
    clipboardMessage.value = '已从剪贴板粘贴';
    clipboardMessageType.value = 'success';
  } catch (err) {
    clipboardMessage.value = '粘贴失败: ' + err.message;
    clipboardMessageType.value = 'error';
    console.error('Failed to paste:', err);
  }
  
  setTimeout(() => {
    clipboardMessage.value = '';
    clipboardMessageType.value = '';
  }, 3000);
};

// 组件挂载和卸载
onMounted(() => {
  // 加载存储数据
  loadAllLocalStorage();
  loadAllSessionStorage();
  
  // 监听窗口大小变化
  window.addEventListener('resize', updateWindowSize);
  
  // 监听网络状态变化
  window.addEventListener('online', handleOnline);
  window.addEventListener('offline', handleOffline);
  
  // 更新网络信息
  if (navigator.connection) {
    navigator.connection.addEventListener('change', updateNetworkInfo);
    updateNetworkInfo();
  }
});

onUnmounted(() => {
  // 停止鼠标跟踪
  if (isTrackingMouse.value) {
    window.removeEventListener('mousemove', updateMousePosition);
  }
  
  // 清理事件监听器
  window.removeEventListener('resize', updateWindowSize);
  window.removeEventListener('online', handleOnline);
  window.removeEventListener('offline', handleOffline);
  
  if (navigator.connection) {
    navigator.connection.removeEventListener('change', updateNetworkInfo);
  }
});
</script>

<style scoped>
.demo-container {
  max-width: 1200px;
  margin: 0 auto;
  padding: 20px;
}

.demo-title {
  font-size: 28px;
  color: #333;
  margin-bottom: 30px;
  text-align: center;
  font-weight: 600;
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
}

.demo-tabs {
  display: flex;
  gap: 10px;
  margin-bottom: 20px;
  border-bottom: 2px solid #eee;
  overflow-x: auto;
  padding-bottom: 10px;
}

.tab-button {
  padding: 12px 24px;
  background: #f5f5f5;
  border: none;
  border-radius: 6px 6px 0 0;
  cursor: pointer;
  font-size: 16px;
  font-weight: 500;
  color: #666;
  transition: all 0.3s ease;
  white-space: nowrap;
}

.tab-button:hover {
  background: #e8e8e8;
  color: #333;
}

.tab-button.active {
  background: #667eea;
  color: white;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}

.tab-content {
  background: white;
  border-radius: 8px;
  padding: 20px;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.05);
}

.tab-pane {
  animation: fadeIn 0.3s ease;
}

.demo-section {
  margin-bottom: 40px;
}

.section-title {
  font-size: 22px;
  color: #333;
  margin-bottom: 15px;
  font-weight: 600;
  border-left: 4px solid #667eea;
  padding-left: 12px;
}

.demo-description {
  margin-bottom: 20px;
  padding: 15px;
  background: #f8f9fa;
  border-radius: 6px;
  border-left: 3px solid #6c757d;
}

.demo-description p {
  margin: 0;
  color: #555;
  line-height: 1.6;
}

.demo-description code {
  background: #e9ecef;
  padding: 2px 6px;
  border-radius: 4px;
  font-family: 'Courier New', monospace;
  font-size: 0.9em;
}

.demo-actions {
  display: flex;
  gap: 15px;
  margin-bottom: 20px;
  flex-wrap: wrap;
}

.btn {
  padding: 10px 20px;
  border: none;
  border-radius: 6px;
  font-size: 16px;
  font-weight: 500;
  cursor: pointer;
  transition: all 0.3s ease;
}

.btn-primary {
  background: #667eea;
  color: white;
}

.btn-primary:hover {
  background: #5a67d8;
  transform: translateY(-1px);
}

.btn-secondary {
  background: #6c757d;
  color: white;
}

.btn-secondary:hover {
  background: #5a6268;
  transform: translateY(-1px);
}

.btn-outline {
  background: transparent;
  border: 2px solid #667eea;
  color: #667eea;
}

.btn-outline:hover {
  background: #667eea;
  color: white;
}

.btn-danger {
  background: #e53e3e;
  color: white;
}

.btn-danger:hover {
  background: #c53030;
  transform: translateY(-1px);
}

.btn:disabled {
  opacity: 0.6;
  cursor: not-allowed;
  transform: none !important;
}

.form-input {
  padding: 10px 12px;
  border: 2px solid #ddd;
  border-radius: 6px;
  font-size: 16px;
  transition: border-color 0.3s ease;
  width: 100%;
}

.form-input:focus {
  outline: none;
  border-color: #667eea;
  box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
}

/* 统计信息样式 */
.counter-stats,
.fetch-stats {
  display: flex;
  gap: 20px;
  margin-bottom: 20px;
  padding: 15px;
  background: #f0f7ff;
  border-radius: 8px;
  flex-wrap: wrap;
}

.stat-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  min-width: 150px;
}

.stat-label {
  font-size: 14px;
  color: #666;
  margin-bottom: 5px;
  text-align: center;
}

.stat-value {
  font-size: 20px;
  font-weight: 600;
  color: #667eea;
}

.stat-value.even {
  color: #38a169;
}

.stat-value.odd {
  color: #e53e3e;
}

.stat-value.positive {
  color: #38a169;
}

.stat-value.negative {
  color: #e53e3e;
}

/* 错误和加载状态 */
.error-message {
  background: #fed7d7;
  border: 1px solid #feb2b2;
  color: #c53030;
  padding: 15px;
  border-radius: 6px;
  margin-bottom: 20px;
}

.loading-indicator {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 40px;
  color: #666;
}

.spinner {
  width: 40px;
  height: 40px;
  border: 4px solid rgba(102, 126, 234, 0.2);
  border-top: 4px solid #667eea;
  border-radius: 50%;
  animation: spin 1s linear infinite;
  margin-bottom: 20px;
}

@keyframes spin {
  0% { transform: rotate(0deg); }
  100% { transform: rotate(360deg); }
}

/* 数据显示 */
.data-display {
  margin-bottom: 20px;
}

.data-display h4 {
  color: #333;
  margin-bottom: 10px;
}

.data-content {
  background: #f8f9fa;
  border: 1px solid #e9ecef;
  border-radius: 6px;
  max-height: 400px;
  overflow: auto;
}

.data-content pre {
  padding: 15px;
  margin: 0;
  font-family: 'Courier New', monospace;
  font-size: 14px;
  white-space: pre-wrap;
  word-break: break-all;
}

/* 存储管理样式 */
.storage-controls {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: 20px;
  margin-bottom: 30px;
}

.storage-group {
  background: #f8f9fa;
  border: 1px solid #e9ecef;
  border-radius: 8px;
  padding: 20px;
}

.storage-group h4 {
  color: #333;
  margin-bottom: 15px;
  border-bottom: 1px solid #e9ecef;
  padding-bottom: 10px;
}

.input-group {
  margin-bottom: 15px;
}

.input-group label {
  display: block;
  margin-bottom: 5px;
  font-weight: 500;
  color: #555;
}

.action-buttons {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
}

.storage-preview {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: 20px;
}

.preview-group {
  background: #f8f9fa;
  border: 1px solid #e9ecef;
  border-radius: 8px;
  padding: 20px;
}

.preview-group h4 {
  color: #333;
  margin-bottom: 15px;
}

.preview-content {
  background: white;
  border: 1px solid #e9ecef;
  border-radius: 6px;
  max-height: 300px;
  overflow: auto;
}

.preview-content pre {
  padding: 15px;
  margin: 0;
  font-family: 'Courier New', monospace;
  font-size: 14px;
  white-space: pre-wrap;
  word-break: break-all;
}

.empty-message {
  padding: 20px;
  color: #6c757d;
  text-align: center;
  font-style: italic;
}

/* 浏览器API样式 */
.browser-apis {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: 20px;
  margin-bottom: 30px;
}

.api-card {
  background: white;
  border: 1px solid #e9ecef;
  border-radius: 8px;
  padding: 20px;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
}

.api-card h4 {
  color: #667eea;
  margin-bottom: 15px;
  border-bottom: 1px solid #e9ecef;
  padding-bottom: 10px;
}

.mouse-position,
.window-size,
.network-status {
  margin-bottom: 15px;
}

.position-item,
.size-item,
.status-item {
  display: flex;
  justify-content: space-between;
  padding: 8px 0;
  border-bottom: 1px solid #f1f1f1;
}

.position-item:last-child,
.size-item:last-child,
.status-item:last-child {
  border-bottom: none;
}

.position-label,
.size-label,
.status-label {
  font-weight: 500;
  color: #555;
}

.position-value,
.size-value,
.status-value {
  font-family: 'Courier New', monospace;
  font-weight: 600;
  color: #667eea;
}

.status-value.online {
  color: #38a169;
}

.status-value.offline {
  color: #e53e3e;
}

.window-type {
  display: flex;
  justify-content: space-between;
  padding: 10px;
  background: #f8f9fa;
  border-radius: 6px;
  margin-top: 15px;
}

.type-label {
  font-weight: 500;
  color: #555;
}

.type-value {
  font-weight: 600;
  padding: 2px 8px;
  border-radius: 4px;
}

.type-value.mobile {
  background: #fed7d7;
  color: #c53030;
}

.type-value.tablet {
  background: #feebc8;
  color: #d69e2e;
}

.type-value.desktop {
  background: #c6f6d5;
  color: #2f855a;
}

.clipboard-message {
  margin-top: 15px;
  padding: 10px;
  border-radius: 6px;
  font-weight: 500;
  text-align: center;
}

.clipboard-message.success {
  background: #c6f6d5;
  color: #2f855a;
}

.clipboard-message.error {
  background: #fed7d7;
  color: #c53030;
}

/* 高级组合函数模式 */
.advanced-patterns {
  display: grid;
  grid-template-columns: 1fr;
  gap: 30px;
  margin-bottom: 30px;
}

.pattern-card {
  background: white;
  border: 1px solid #e9ecef;
  border-radius: 8px;
  padding: 25px;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
}

.pattern-title {
  color: #667eea;
  margin-bottom: 15px;
  font-size: 18px;
  font-weight: 600;
}

.pattern-content p {
  margin-bottom: 15px;
  color: #555;
  line-height: 1.6;
}

.code-snippet {
  background: #f8f9fa;
  border: 1px solid #e9ecef;
  border-radius: 6px;
  overflow: auto;
  max-height: 400px;
}

.code-snippet pre {
  padding: 15px;
  margin: 0;
  font-family: 'Courier New', monospace;
  font-size: 14px;
  white-space: pre-wrap;
  word-break: break-all;
  line-height: 1.5;
}

/* 代码示例 */
.code-sample {
  margin-top: 30px;
  background: #f8f9fa;
  border: 1px solid #e9ecef;
  border-radius: 8px;
  overflow: hidden;
}

.code-sample h4 {
  background: #667eea;
  color: white;
  margin: 0;
  padding: 12px 15px;
  font-size: 16px;
  font-weight: 500;
}

.code-sample pre {
  padding: 15px;
  margin: 0;
  font-family: 'Courier New', monospace;
  font-size: 14px;
  white-space: pre-wrap;
  word-break: break-all;
  line-height: 1.5;
  max-height: 500px;
  overflow: auto;
}

/* 动画 */
@keyframes fadeIn {
  from {
    opacity: 0;
    transform: translateY(10px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

/* 响应式设计 */
@media (max-width: 768px) {
  .demo-tabs {
    flex-direction: column;
  }
  
  .tab-button {
    border-radius: 6px;
  }
  
  .demo-actions {
    flex-direction: column;
  }
  
  .counter-stats,
  .fetch-stats {
    flex-direction: column;
    gap: 15px;
  }
  
  .stat-item {
    min-width: auto;
    text-align: center;
  }
  
  .storage-controls,
  .storage-preview,
  .browser-apis {
    grid-template-columns: 1fr;
  }
  
  .position-item,
  .size-item,
  .status-item,
  .window-type {
    flex-direction: column;
    gap: 5px;
    text-align: center;
  }
}
</style>